﻿using System.IO;
using System.Reflection;
using Microsoft.Win32;
using Startup.Base.Commands;
using Startup.MVVM;
using Startup.Shell.Domain;
using Startup.Shell.Modules.ClassEditorModule;
using Startup.Shell.Modules.ClassesModule;
using Startup.Shell.Modules.WindowDesignerModule;

namespace Startup.Shell.Modules.MainShellModule
{
	public class MainShellViewModel : ViewModelBase
	{
		private readonly DomainModel _model;

		// commands
		private readonly SimpleCommand _newProjectCommand;
		private readonly SimpleCommand _openProjectCommand;
		private readonly SimpleCommand _saveProjectCommand;
		private readonly SimpleCommand _saveAsProjectCommand;
		private readonly SimpleCommand _generateProjectCommand;

		public MainShellViewModel(DomainModel model)
		{
			_model = model;
			
			// commands
			_newProjectCommand = new SimpleCommand(_model.NewProject);
			_openProjectCommand = new SimpleCommand(OnOpenProject);
			_saveProjectCommand = new SimpleCommand(_model.SaveProject, () => _model.Project != null && _model.Project.HasSourceFile);
			_saveAsProjectCommand = new SimpleCommand(OnSaveAsProject, () => _model.Project != null);
			_generateProjectCommand = new SimpleCommand(OnGenerateProject, () => _model.Project != null);

			// events
			_model.ProjectChanged += OnProjectChanged;
		}
		
		public static MainShellViewModel Designer
		{
			get
			{
				var model = new DomainModel();
				model.NewProject();
				model.Project.Name = "Test Project";

				return new MainShellViewModel(model);
			}
		}

		public string Title
		{
			get
			{
				if (_model.Project == null)
					return "Startup.NET";

				return string.Format("Startup.NET: {0}", _model.Project.Name);
			}
		}

		public SimpleCommand NewProjectCommand
		{
			get { return _newProjectCommand; }
		}

		public SimpleCommand OpenProjectCommand
		{
			get { return _openProjectCommand; }
		}

		public SimpleCommand SaveProjectCommand
		{
			get { return _saveProjectCommand; }
		}

		public SimpleCommand SaveAsProjectCommand
		{
			get { return _saveAsProjectCommand; }
		}

		public ClassesViewModel ClassesViewModel
		{
			get
			{
				if (_model.Project == null)
					return null;

				var model = new ClassesModel(_model.Project.Classes);
				return new ClassesViewModel(model);
			}
		}

		public SimpleCommand GenerateProjectCommand
		{
			get { return _generateProjectCommand; }
		}

		public WindowDesignerViewModel WindowDesignerViewModel
		{
			get 
			{
				if (_model.Project == null)
					return null;

				var model = new WindowDesignerModel(_model.Project);
				return new WindowDesignerViewModel(model);
			}
		}

		private void OnProjectChanged()
		{
			RaisePropertyChanged("Title");

			_saveProjectCommand.RaiseCanExecuteChanged();
			_saveAsProjectCommand.RaiseCanExecuteChanged();
			_generateProjectCommand.RaiseCanExecuteChanged();

			RaisePropertyChanged("ClassesViewModel");
			RaisePropertyChanged("DomainClassViewModel");
			RaisePropertyChanged("WindowDesignerViewModel");
		}

		private void OnOpenProject()
		{
			var window = new OpenFileDialog();
			bool? result = window.ShowDialog(App.Current.MainWindow);

			if (!result.Value)
				return;

			_model.OpenProject(window.FileName);
		}

		private void OnSaveAsProject()
		{
			var window = new SaveFileDialog();
			bool? result = window.ShowDialog(App.Current.MainWindow);

			if (!result.Value)
				return;

			_model.Project.SaveAs(window.FileName);

			// update save command
			_saveProjectCommand.RaiseCanExecuteChanged();
		}

		private void OnGenerateProject()
		{
			// TODO: choose folder by dialog
			string assemblyPath = Assembly.GetExecutingAssembly().Location;
			string homeDir = Path.GetDirectoryName(assemblyPath);
			string projectDir = Path.Combine(homeDir, "Project");

			if (Directory.Exists(projectDir))
				Directory.Delete(projectDir, true);
			
			_model.GenerateProject(projectDir);
		}
	}
}
